﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace ZombieGame
{
    public class Player : Entity
    {
        private float _delay = 0f;
        private float _relDelay = 0f;
        public float Invulnerable = 0f;
        public float Speed = 1f;
        public ulong Score = 0;
        public Weapon Weapon;
        public float MaxHealth;
        public string Name;

        public override float Layer
        {
            get { return 0.9f; }
        }

        public Player() :
            base()
        {
            Health = 2f;
            MaxHealth = 2f;
            Origin = new Vector2(5f, 8f);
            Size = new Vector2(16f, 16f);
            Animation.Add(ZombieGame.Current.Content.Load<Texture2D>("Character"));
            ImageData.Add(Drawable.TextureToColor(Animation[0]));
            Weapon = Weapon.DesertEagle;
            Name = "";
            Color = Color.White;
        }

        public override void Update(GameTime time)
        {
            if (Alive)
            {
                float t = (float)time.ElapsedGameTime.TotalSeconds / (1f / 60f);
                if (InputHandler.IsUp(Keys.W) && InputHandler.IsUp(Keys.S))
                    Velocity.Y -= Math.Sign(Velocity.Y) * Math.Min(Math.Abs(0 - Velocity.Y), 10f) * t * Speed;
                if (InputHandler.IsUp(Keys.A) && InputHandler.IsUp(Keys.D))
                    Velocity.X -= Math.Sign(Velocity.X) * Math.Min(Math.Abs(0 - Velocity.X), 10f) * t * Speed;
                if (InputHandler.IsDown(Keys.W))
                    Velocity.Y += Math.Max(-256f - Velocity.Y, -10f) * t * Speed;
                if (InputHandler.IsDown(Keys.S))
                    Velocity.Y += Math.Min(256f - Velocity.Y, 10f) * t * Speed;
                if (InputHandler.IsDown(Keys.A))
                    Velocity.X += Math.Max(-256f - Velocity.X, -10f) * t * Speed;
                if (InputHandler.IsDown(Keys.D))
                    Velocity.X += Math.Min(256f - Velocity.X, 10f) * t * Speed;
                foreach (Wall w in ZombieGame.Current.World.Walls)
                {
                    Vector2 col = w.Collide(this);
                    if (col != new Vector2(-1f))
                        Velocity = Position - col;
                }
                _delay += (float)time.ElapsedGameTime.TotalSeconds;
                if (Invulnerable > 0)
                    Invulnerable -= (float)time.ElapsedGameTime.TotalSeconds;
                if (Invulnerable < 0)
                    Invulnerable = 0;
                if (Weapon.Reloading)
                    _relDelay += (float)time.ElapsedGameTime.TotalSeconds;
                if (Weapon.Clip == 0 && Weapon.Ammo > 0)
                {
                    Weapon.Reloading = true;
                    Speed = 0.5f;
                }
                if (_relDelay > Weapon.ReloadCooldown)
                {
                    Speed = 1f;
                    Weapon.Reload();
                    _relDelay = 0f;
                }
                if (_delay > 1f / Weapon.RateOfFire)
                {
                    if (InputHandler.CurrentMouseState.LeftButton == ButtonState.Pressed && (Weapon.Type == WeaponType.Automatic || Weapon.Type == WeaponType.Laser))
                        FireBullet();
                    if (InputHandler.MouseLPress() && (Weapon.Type == WeaponType.SemiAutomatic || Weapon.Type == WeaponType.Shotgun))
                        FireBullet();
                }
                if (Health < MaxHealth)
                    Health += 0.1f * (float)time.ElapsedGameTime.TotalSeconds;
                if (Health > MaxHealth)
                    Health = MaxHealth;
                if (InputHandler.IsNewDown(Keys.R) && Weapon.Ammo > 0)
                {
                    Speed = 0.5f;
                    Weapon.Reloading = true;
                }
                Rotation = (float)Math.Atan2(ZombieGame.Current.MousePosition.Y - Position.Y, ZombieGame.Current.MousePosition.X - Position.X);
                Camera.Position = this.Position - new Vector2(Camera.Rectangle.Width / 2f, Camera.Rectangle.Height / 2f);
            }
            base.Update(time);
        }

        public override void Draw(SpriteBatch batch)
        {
            if (Alive)
            {
                ZombieGame.TextDrawer.DrawString(ZombieGame.Font1, "Score: " + Score, new Vector2(14f), Color.Black);
                ZombieGame.TextDrawer.DrawString(ZombieGame.Font1, Weapon.Clip + "\\" + Weapon.Ammo, new Vector2(ZombieGame.Current.GraphicsDevice.Viewport.Width - 14f - ZombieGame.Font1.MeasureString(Weapon.Clip + "\\" + Weapon.Ammo).X, 14f), Color.Black);
                ZombieGame.TextDrawer.DrawString(ZombieGame.Font1, Weapon.Name, new Vector2(ZombieGame.Current.GraphicsDevice.Viewport.Width - 14f - ZombieGame.Font1.MeasureString(Weapon.Name).X, 42f), Color.Black);
            }
            if ((int)(Invulnerable * 16) % 2 == 0)
                base.Draw(batch);
        }

        public void FireBullet()
        {
            if (Weapon.Clip > 0)
            {
                if (Weapon.Reloading)
                    Weapon.Reloading = false;
                if (Weapon.Type == WeaponType.Laser)
                    ZombieGame.Current.World.Entities.Add(new LaserProjectile(this, Rotation));
                else
                    if (Weapon.Type != WeaponType.Shotgun)
                        ZombieGame.Current.World.Entities.Add(new Projectile(this, Rotation));
                    else
                    {
                        Projectile[] p = new Projectile[4];
                        p[0] = new Projectile(this, Rotation - MathHelper.ToRadians(5f));
                        p[1] = new Projectile(this, Rotation - MathHelper.ToRadians(15f));
                        p[2] = new Projectile(this, Rotation + MathHelper.ToRadians(5f));
                        p[3] = new Projectile(this, Rotation + MathHelper.ToRadians(15f));
                        ZombieGame.Current.World.Entities.AddRange(p);
                    }
                Weapon.Clip--;
                _delay = 0;
            }
        }

        public override void Dispose()
        {
            Weapon = null;
            _delay = 0f;
            Invulnerable = 0f;
            _relDelay = 0f;
            Score = 0;
            MaxHealth = 0f;
            base.Dispose();
        }

        public override object Clone()
        {
            Player clone = new Player();
            clone.Animation = this.Animation;
            clone._delay = this._delay;
            clone._relDelay = this._relDelay;
            clone.Weapon = this.Weapon;
            clone.Score = this.Score;
            clone.MaxHealth = this.MaxHealth;
            clone.Health = this.Health;
            clone.Alive = this.Alive;
            clone.Color = this.Color;
            clone.ImageData = this.ImageData;
            clone.Velocity = this.Velocity;
            clone.Visible = this.Visible;
            clone.State = this.State;
            clone.Frame = this.Frame;
            clone.Position = this.Position;
            clone.Size = this.Size;
            clone.Scale = this.Scale;
            clone.Rotation = this.Rotation;
            clone.Origin = this.Origin;
            clone.Matrix = this.Matrix;
            return clone;
        }

        public override void Kill()
        {
            Alive = false;
            Health = 0f;
            try
            {
                ZombieGame.Current.World.Players.Remove(this);
            }
            catch
            {
            }
            Dispose();
        }
    }
}
